/*
 *  * Copyright (C) 2021 Huawei Device Co., Ltd.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package com.sefford.circularprogressdrawable.sample.slice;

import com.sefford.circularprogressdrawable.CircularProgressDrawable;
import com.sefford.circularprogressdrawable.ResourceTable;
import com.sefford.circularprogressdrawable.sample.utils.ResUtil;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.render.Canvas;

import static com.sefford.circularprogressdrawable.sample.utils.Constants.*;

public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener {

    private Image ivDrawable;
    private Button btStyle1;
    private Button btStyle3;
    private Button btStyle4;
    private Animator currentAnimation;
    private CircularProgressDrawable drawable;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        ivDrawable = (Image) findComponentById(ResourceTable.Id_iv_drawable);
        btStyle1 = (Button) findComponentById(ResourceTable.Id_bt_style_1);
        btStyle3 = (Button) findComponentById(ResourceTable.Id_bt_style_3);
        btStyle4 = (Button) findComponentById(ResourceTable.Id_bt_style_4);

        drawable = new CircularProgressDrawable.Builder()
                .setRingWidth((int) ResUtil.getDimen(getContext(), ResourceTable.Float_drawable_ring_size))
                .setOutlineColor(ResUtil.getColor(getContext(), ResourceTable.Color_darker_gray))
                .setRingColor(ResUtil.getColor(getContext(), ResourceTable.Color_holo_green_light))
                .setCenterColor(ResUtil.getColor(getContext(), ResourceTable.Color_holo_blue_dark))
                .create();
        ivDrawable.addDrawTask(new Component.DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                drawable.setComponent(component);
                drawable.drawToCanvas(canvas);
            }
        });
        hookUpListeners();
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    private void hookUpListeners() {
        ivDrawable.setClickedListener(this);
        btStyle1.setClickedListener(this);
        btStyle3.setClickedListener(this);
        btStyle4.setClickedListener(this);
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    public void onClick(Component component) {
        if (currentAnimation != null) {
            currentAnimation.cancel();
        }
        switch (component.getId()) {
            case ResourceTable.Id_bt_style_1:
                currentAnimation = prepareStyle1Animation();
                break;
            case ResourceTable.Id_bt_style_3:
                currentAnimation = prepareStyle3Animation();
                break;
            case ResourceTable.Id_bt_style_4:
            default:
                currentAnimation = preparePulseAnimation();
                break;
        }
        currentAnimation.start();
    }

    private Animator prepareStyle1Animation() {
        AnimatorGroup animation = new AnimatorGroup();
        AnimatorValue indeterminateAnimation = new AnimatorValue();
        indeterminateAnimation.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float progressProperty = INDETERIMINATE_CENTER_DURATION * v;
                drawable.setProgress(progressProperty);
            }
        });
        indeterminateAnimation.setDuration(INDETERIMINATE_CENTER_DURATION);
        indeterminateAnimation.start();

        AnimatorValue innerCircleAnimation = new AnimatorValue();
        innerCircleAnimation.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float circleScaleProperty = START_VALUE + (END_VALUE - START_VALUE) * v;
                drawable.setCircleScale(circleScaleProperty);
            }
        });
        innerCircleAnimation.setDuration(INDETERIMINATE_CENTER_DURATION);
        innerCircleAnimation.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                drawable.setIndeterminate(true);
            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                indeterminateAnimation.end();
                drawable.setIndeterminate(false);
                drawable.setProgress(END_PROGRESS);
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        innerCircleAnimation.start();
        animation.runSerially(innerCircleAnimation, indeterminateAnimation);
        return animation;
    }

    private Animator prepareStyle3Animation() {
        AnimatorGroup animation = new AnimatorGroup();

        AnimatorValue progressAnimation = new AnimatorValue();
        progressAnimation.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float progressProperty = END_VALUE + (START_VALUE - END_VALUE) * v;
                drawable.setProgress(progressProperty);
            }
        });
        progressAnimation.setDuration(SLING_DURATION);
        progressAnimation.setCurveType(Animator.CurveType.ANTICIPATE);

        AnimatorValue innerCircleAnimation = new AnimatorValue();
        innerCircleAnimation.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float circleScaleProperty = END_VALUE + (START_VALUE - END_VALUE) * v;
                drawable.setCircleScale(circleScaleProperty);
            }
        });
        innerCircleAnimation.setDuration(SLING_DURATION);
        innerCircleAnimation.setCurveType(Animator.CurveType.ANTICIPATE);

        AnimatorValue invertedProgress = new AnimatorValue();
        invertedProgress.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float progressProperty = START_VALUE + (END_VALUE - START_VALUE) * v;
                drawable.setProgress(progressProperty);
            }
        });
        invertedProgress.setDuration(SLING_DURATION);
        invertedProgress.setCurveType(Animator.CurveType.OVERSHOOT);

        AnimatorValue invertedCircle = new AnimatorValue();
        invertedCircle.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float circleScaleProperty = START_VALUE + (END_VALUE - START_VALUE) * v;
                drawable.setCircleScale(circleScaleProperty);
            }
        });
        invertedCircle.setDuration(SLING_DURATION);
        invertedCircle.setCurveType(Animator.CurveType.OVERSHOOT);

        animation.runSerially(progressAnimation, innerCircleAnimation, invertedProgress, invertedCircle);
        return animation;
    }

    private Animator preparePulseAnimation() {
        AnimatorGroup animation = new AnimatorGroup();
        AnimatorValue firstBounce = new AnimatorValue();
        firstBounce.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float circleScaleProperty = drawable.getCircleScale() + (FIRST_BOUNCE - drawable.getCircleScale()) * v;
                drawable.setCircleScale(circleScaleProperty);
            }
        });
        firstBounce.setDuration(PULSE_DURATION);
        firstBounce.setCurveType(Animator.CurveType.CYCLE);
        firstBounce.start();


        AnimatorValue secondBounce = new AnimatorValue();
        secondBounce.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float circleScaleProperty = END_VALUE + (SECOND_BOUNCE - END_VALUE) * v;
                drawable.setCircleScale(circleScaleProperty);
            }
        });
        secondBounce.setDuration(PULSE_DURATION);
        secondBounce.setCurveType(Animator.CurveType.CYCLE);
        secondBounce.start();

        AnimatorValue thirdBounce = new AnimatorValue();
        thirdBounce.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float circleScaleProperty = END_VALUE + (THIRD_BOUNCE - END_VALUE) * v;
                drawable.setCircleScale(circleScaleProperty);
                animatorValue.start();

            }
        });
        thirdBounce.setDuration(PULSE_DURATION);
        thirdBounce.setCurveType(Animator.CurveType.CYCLE);
        thirdBounce.start();
        animation.runSerially(firstBounce, secondBounce, thirdBounce);
        return animation;
    }
}
